package org.seed.quantum.nio;

import java.io.IOException;
import java.nio.channels.AsynchronousChannelGroup;
import java.nio.channels.AsynchronousServerSocketChannel;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.channels.spi.AsynchronousChannelProvider;
import java.util.concurrent.*;

public final class AsynchronousChannelProviderExt extends AsynchronousChannelProvider {

    @Override
    public AsynchronousChannelGroup openAsynchronousChannelGroup(int nThreads, ThreadFactory threadFactory) throws IOException {
        return new AsynchronousChannelGroupExt(this, new ThreadPoolExecutor(nThreads, nThreads,
                0L, TimeUnit.MILLISECONDS,
                new ArrayBlockingQueue<>(nThreads),
                threadFactory), nThreads);
    }

    @Override
    public AsynchronousChannelGroup openAsynchronousChannelGroup(ExecutorService executor, int initialSize) throws IOException {
        return new AsynchronousChannelGroupExt(this, executor, initialSize);
    }

    @Override
    public AsynchronousServerSocketChannel openAsynchronousServerSocketChannel(AsynchronousChannelGroup group) throws IOException {
        return new AsynchronousServerSocketChannelExt(checkAndGet(group));
    }

    @Override
    public AsynchronousSocketChannel openAsynchronousSocketChannel(AsynchronousChannelGroup group) throws IOException {
        return new AsynchronousSocketChannelExt(checkAndGet(group), SocketChannel.open());
    }

    private AsynchronousChannelGroupExt checkAndGet(AsynchronousChannelGroup group) {
        if (!(group instanceof AsynchronousChannelGroupExt)) {
            throw new RuntimeException("invalid class");
        }
        return (AsynchronousChannelGroupExt) group;
    }

}
